/*
获取文件属性、时间、大小等信息，设置文件属性
    利用程序的命令行参数（输入1个文件路径参数，获取第1个参数指定的文件的属性、时间和大小；输入2个文件路径参数，获取第1个参数指定的属性、时间、大小，设置第2个参数指定的文件属性）

GetFileAttributesEx、GetFileAttributes函数
SetFileAttributes函数
WIN32_FILE_ATTRIBUTE_DATA结构
FileTimeToLocalFileTime、FileTimeToSystemTime函数
FILETIME、SYSTEMTIME结构
*/
#include <windows.h>
#include <tchar.h>

void ShowFileInfo(PCTSTR FileName);
void ConvertTime(const FILETIME *ftTime);
PCTSTR IntWeekToCh(int iDayOfWeek);
void ShowFileSize(DWORD dwFileSizeHigh, DWORD dwFileSizeLow);
void ByteToKMGT1(ULONGLONG FileSize);
void ShowFileAttr(DWORD dwFileAttributes);
void SetFileAttr(PCTSTR FileName);

int main(int argc, const char *argv[])
{
    if (argc==2) {
        ShowFileInfo(*(argv+1));
    } else if (argc==3) {
        ShowFileInfo(*(argv+1));
        SetFileAttr(*(argv+2));
    } else if (argc!=3) {
        _tprintf(TEXT("请输入参数\n" "显示第一个参数指定文件的属性、时间、大小；\n" "将第二个参数的属性设置为隐藏、只读。\n"));
    }

    return 0;
}

/* 获取并显示文件属性：创建时间、 最后访问时间、最后修改时间、大小、属性 */
void ShowFileInfo(PCTSTR FileName)
{
    WIN32_FILE_ATTRIBUTE_DATA FileInformation;

    if (!GetFileAttributesEx(FileName, GetFileExInfoStandard, &FileInformation)) {
        _tprintf(TEXT("获取文件属性错误。错误代码是%lu。\n"), GetLastError());
    } else {
        _tprintf(TEXT("文件：\t\"%s\"\n\n"), FileName);

        _tprintf(TEXT("创建时间：\t"));
        // 将文件时间转化为本地文件时间，再转化为系统时间
        ConvertTime(&FileInformation.ftCreationTime);

        _tprintf(TEXT("最后访问时间：\t"));
        ConvertTime(&FileInformation.ftLastAccessTime);

        _tprintf(TEXT("最后修改时间：\t"));
        ConvertTime(&FileInformation.ftLastWriteTime);

        // 打印文件大小
        ShowFileSize(FileInformation.nFileSizeHigh, FileInformation.nFileSizeLow);

        // 打印文件属性
        ShowFileAttr(FileInformation.dwFileAttributes);
    }
}

/* 将文件时间转化为本地文件时间，再转化为系统时间 */
void ConvertTime(const FILETIME *ftTime)
{
    FILETIME ftLocalFileTime;
    SYSTEMTIME SystemTime;

    if (FileTimeToLocalFileTime(ftTime, &ftLocalFileTime)) {
        FileTimeToSystemTime(ftTime, &SystemTime);

        _tprintf(TEXT("%4d年%02d月%02d日星期%s，%02d时%02d分%02d秒\n"), SystemTime.wYear, SystemTime.wMonth,  SystemTime.wDay, IntWeekToCh(SystemTime.wDayOfWeek), SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond);
    }
}

/* 打印星期 */
PCTSTR IntWeekToCh(int iDayOfWeek)
{
    if (iDayOfWeek==1) {
        return "一";
    } else if (iDayOfWeek==2) {
        return "二";
    } else if (iDayOfWeek==3) {
        return "三";
    } else if (iDayOfWeek==4) {
        return "四";
    } else if (iDayOfWeek==5) {
        return "五";
    } else if (iDayOfWeek==6) {
        return "六";
    } else if (iDayOfWeek==0) {
        return "日";
    }

    return NULL;
}

/* 打印文件大小 */
void ShowFileSize(DWORD dwFileSizeHigh, DWORD dwFileSizeLow)
{
    ULONGLONG FileSize = dwFileSizeHigh;

    // 将文件大小的高位和低位连接为64位的长整型
    FileSize <<= sizeof(WORD)*8;
    // FileSize <<= 32;
    FileSize += dwFileSizeLow;

    // _tprintf(TEXT("%I64u %I64u %I64u\n"), sizeof(WORD), sizeof(DWORD),sizeof(WORD)*8);

    _tprintf(TEXT("属性：\t%I64u字节，"), FileSize);
    ByteToKMGT1(FileSize);
}

/* 把字节动态转换为KB、MB、GB、TB */
void ByteToKMGT1(ULONGLONG FileSize)
{
    ULONGLONG Temp = FileSize;
    // 统计换算1024的次数
    int iCnt = 0;

    while (Temp>=1024) {
        Temp /= 1024;
        iCnt++;
    }

    switch (iCnt) {
        case 0:
            _tprintf(TEXT("共计 %d B\n"), (int)FileSize);
            break;
        case 1:
            _tprintf(TEXT("共计 %.4f KB\n"), FileSize/(float)1024);
            break;
        case 2:
            _tprintf(TEXT("共计 %.4f MB\n"), FileSize/((float)1024*1024));
            break;
        case 3:
            _tprintf(TEXT("共计 %.4f GB\n"), FileSize/((float)1024*1024*1024));
            break;
        case 4:
            _tprintf(TEXT("共计 %.4f TB\n"), FileSize/((float)1024*1024*1024*1024));
            break;
        default :
            break;            
    }
}

/* 打印文件属性 */
void ShowFileAttr(DWORD dwFileAttributes)
{
    _tprintf(TEXT("属性：\t"));

    if (dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) {
        _tprintf(TEXT("<ARCHIVE>"));
    }
    if (dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) {
        _tprintf(TEXT("<压缩>"));
    }
    if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
        _tprintf(TEXT("<目录>"));
    }
    if (dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) {
        _tprintf(TEXT("<加密>"));
    }
    if (dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) {
        _tprintf(TEXT("<隐藏>"));
    }
    if (dwFileAttributes & FILE_ATTRIBUTE_NORMAL) {
        _tprintf(TEXT("<NORMAL>"));
    }
    if (dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) {
        _tprintf(TEXT("<OFFLINE>"));
    }
    if (dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
        _tprintf(TEXT("<只读>"));
    }
    if (dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) {
        _tprintf(TEXT("<SPARSE>"));
    }
    if (dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) {
        _tprintf(TEXT("<系统文件>"));
    }
    if (dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) {
        _tprintf(TEXT("<临时文件>"));
    }    
}

/* 设置属性 */
void SetFileAttr(PCTSTR FileName)
{
    DWORD dwFileAttributes = GetFileAttributes(FileName);

    dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM;
    dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
    dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;

    if (SetFileAttributes(FileName, dwFileAttributes)) {
        _tprintf(TEXT("\n\n已经将\"%s\"文件属性设置为系统、只读、隐藏。\n"), FileName);
    } else {
        _tprintf(TEXT("设置\"%s\"文件属性出错。错误代码是%lu。\n"), FileName, GetLastError());
    }

    if (SetFileAttributes(FileName, FILE_ATTRIBUTE_NORMAL)) {
        _tprintf(TEXT("已经将\"%s\"文件属性还原为正常属性。\n"), FileName);
    } else {
        _tprintf(TEXT("设置\"%s\"文件属性出错。错误代码是%lu。\n"), FileName, GetLastError());
    }
}